package gameEngine.game;

import exportSystem.statistics.ExperimentLog;
import exportSystem.statistics.Statistics;
import gameEngine.agents.Agent;
import gameEngine.agents.LoggedAgent;
import gameEngine.agents.observationSystem.Observation;
import gameEngine.agents.observationSystem.samples.Sample;
import gameEngine.agents.observationSystem.samples.SampleFactory;
import gameEngine.environment.Environment;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

import org.apache.log4j.Logger;

/**
 * game based on turns. 
 * holds an ArrayList of Agents
 * @author alon
 *
 */
public class TurnBasedScoredGame implements Game {

	private double score;
	private ArrayList<Agent> agents;
	private Environment env;
	private Agent curentPlayer;
	private int numberOfTurns; 
	private int turnNumber;
	//private Observation observation;
	Logger log=Logger.getLogger(this.getClass());
	public static boolean RUNNIG_FLAG=true;
	private int id;
	
	public TurnBasedScoredGame(int turns,ArrayList<Agent> agents,Environment env,Observation observation,int id){
		score=0.0;
		turnNumber=0;
		numberOfTurns=turns;
		this.setAgents(agents);
		this.env=env;
		//this.observation=observation;
		//curentPlayer=new LoggedAgent(new CSVLogger(id), this, Massage_Type.CSV);
		//set a random agent to start. use random number generator
		//and the % to normalize the random number to agents range 
		Random generator=new Random();
		int index=generator.nextInt();
		index=Math.abs(index)%agents.size();
		//curentPlayer.setAgent(agents.get(index));
		curentPlayer=agents.get(index);
		this.id=id;
	}
	
	/**
	 * simple logic for turn base scored game
	 * run over all turns and sum up the score
	 * creates a massage each turn to be used by the {@link LoggedAgent} 
	 * creates a turn data as {@link Sample} and pass it to all agents to analyze
	 */
	public double play(){
		turnNumber=0;
		Statistics.initStatistics(agents);
		RUNNIG_FLAG=true;
		log.info("game "+id+" has started");
		while(numberOfTurns>turnNumber&&RUNNIG_FLAG){
			double result=curentPlayer.play();;
			score+=result;
			//record observations
			int ind=curentPlayer.chooseNextPlayer();
			Sample s=SampleFactory.create(0, curentPlayer.getID(), result, turnNumber, ind);
			//add this to the observation system
			//observation.addSample(s);
			//add sample to experiment log
			ExperimentLog.getInstance().addTurnData(id, s);
			//let every agent analyze last turn sample
			for(Agent a: agents){
				a.analyzeSample(s);
			}
			log.debug("palying turn "+turnNumber+ "agent "+curentPlayer.getID()+" scored "+result
					+"and selected agent "+ind );
			//curentPlayer.setAgent(agents.get(ind - 1));
			curentPlayer=getAgentByID(ind);
			turnNumber++;
		}
		//done playing, flush remaining data in logged agent and add the total score.
		//curentPlayer.getLog().setScore(score);
		//curentPlayer.getLog().flush();
		log.info("game "+id+" done with total score of "+score);
		Statistics.addAgentStopTurn(agents.get(0).getID(), turnNumber);
		return score;
	}

	private Agent getAgentByID(int id){
		for(Agent a:agents){
			if(a.getID()==id)
				return a;
		}
		log.error("could not fine agent with id "+id);
		return null;
	}
	
	public double getScore() {
		return score;
	}

	public void setScore(double score) {
		this.score = score;
	}

	
	public List<Agent> getAgents() {
		return agents;
	}

	public void setAgents(ArrayList<Agent> agents) {
		this.agents = agents;
	}

	public Environment getEnv() {
		return env;
	}

	public void setEnv(Environment env) {
		this.env = env;
	}

	public Agent getCurentPlayer() {
		return curentPlayer;
	}

	public void setCurentPlayer(Agent curentPlayer) {
		this.curentPlayer = curentPlayer;
	}

	public int getNumberOfTurns() {
		return numberOfTurns;
	}

	public void setNumberOfTurns(int numberOfTurns) {
		this.numberOfTurns = numberOfTurns;
	}
	
	public int getID(){
		return id;
	}
	
	public int getTurnNumber(){
		return turnNumber;
	}
	
}
